﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PureMVC.Interfaces;
using PureMVC.Other;
using PureMVC.Core;
using System;
using PureMVC.Patterns.Observer;

namespace PureMVC.Patterns.Facade
{
    public partial class Facade : IFacade
    {
        public Facade(string _key)
        {
            if (instanceMap.ContainsKey(_key) && multitonKey != null)
            {
                throw new Exception(MULTITON_MSG);
            }
            InitializeNotifier(_key);
            instanceMap.Add(_key, new Other.WeakLazy<IFacade>(() => this));
            InitializeFacade();
        }

        protected virtual void InitializeFacade()
        {
            InitializeController();
            InitializeModel();
            InitializeView();
        }

        protected virtual void InitializeController()
        {
            controller = Controller.GetInstance(multitonKey, () => new Controller(multitonKey));
        }

        protected virtual void InitializeModel()
        {
            model = Model.GetInstance(multitonKey, () => new Model(multitonKey));
        }

        protected virtual void InitializeView()
        {
            view = View.GetInstance(multitonKey, () => new View(multitonKey));
        }

        public virtual void InitializeNotifier(string _key)
        {
            multitonKey = _key;
        }

        #region command
        public virtual void RegisterCommand(string _notificationName, Func<ICommand> _commandClassRef)
        {
            controller.RegisterCommand(_notificationName, _commandClassRef);
        }

        public virtual void RemoveCommand(string _notificationName)
        {
            controller.RemoveCommand(_notificationName);
        }

        public virtual bool HasCommand(string _notificationName)
        {
            return controller.HasCommand(_notificationName);
        }
        #endregion command

        #region proxy
        public virtual void RegisterProxy(IProxy _proxy)
        {
            model.RegisterProxy(_proxy);
        }

        public virtual IProxy RemoveProxy(string _proxyName)
        {
            return model.RemoveProxy(_proxyName);
        }

        public virtual IProxy RetrieveProxy(string _proxyName)
        {
            return model.RetrieveProxy(_proxyName);
        }

        public virtual bool HasProxy(string _proxyName)
        {
            return model.HasProxy(_proxyName);
        }
        #endregion proxy

        #region mediator
        public virtual void RegisterMediator(IMediator _mediator)
        {
            view.RegisterMediator(_mediator);
        }

        public virtual IMediator RemoveMediator(string _mediatorName)
        {
            return view.RemoveMediator(_mediatorName);
        }

        public virtual IMediator RetrieveMediator(string _mediatorName)
        {
            return view.RetrieveMediator(_mediatorName);
        }

        public virtual bool HasMediator(string _mediatorName)
        {
            return view.HasMediator(_mediatorName);
        }
        #endregion mediator

        public virtual void SendNotification(string _notificationName, object _body = null, string _type = null)
        {
            NotifyObservers(new Notification(_notificationName, _body, _type));
        }

        public virtual void NotifyObservers(INotification _notification)
        {
            view.NotifyObservers(_notification);
        }

        protected string multitonKey = null;
        protected IView view;
        protected IController controller;
        protected IModel model;
    }
}